#import "Term.h"
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <libc.h>

@implementation Term
  
+ new
{
  self = [super newExistingfd:0];
  stack = NULL;
  crlast = NO;
  return self;
}

- pushState
{
  struct stateStack * p;
  p = (struct stateStack *)malloc(sizeof(struct stateStack));
  p->next = stack;
  p->state = currentState;
  stack = p;
  return self;
}

- popState
{
  struct stateStack *p;
  if (stack==NULL) {
    fprintf(stderr,"Term.m error: stack empty on popState\n");
  }
  currentState = stack->state;
  p = stack;
  stack = stack->next;
  free(p);
  return [self activateState];
}

- (int)getchar
{
  char ch;
  int cc;
  [[[self pushState] setRaw] setCrmod];
  cc=read(fd, &ch, 1);
  [self popState];
  if (cc==1) {
    crlast = (ch=='\r' || ch=='\n');
    return ch;
  }
  else
    return EOF;
}

- (int)getcharWithPrompt:(char *)prompt
{
  [self putPrompt:prompt];
  return [self getchar];
}

- (int)getline:(char *)string size:(int)max
{
  char ch;
  int c,i;
  i=0;
  [[[[self pushState] unSetRaw] setCrmod] setEcho];
  while (--max>0 && (c=read(fd,&ch,1))==1 && ch!='\n')
    string[i++]=ch;
  if (ch=='\n')
    string[i++]=ch;
  string[i]=0;
  [self popState];
  crlast=YES;
  return i;
}

- (int)getline:(char *)string size:(int)max WithPrompt:(char *)prompt
{
  [self putPrompt:prompt];
  return [self getline:string size:max];
}

- putString:(char *)string
{
  [[[self pushState] unSetRaw] setCrmod];
  if (crlast && *string=='\n')  // don't skip line at beginning of string
    [self writeOut:string+1];
  else
    [self writeOut:string];
  [self popState];
  crlast = (string[strlen(string)-1]=='\n');
  return self;
}

- putPrompt:(char *)string
{
  [[[self pushState] unSetRaw] setCrmod];
  printf("%s",string);
  fflush(stdout);
  [self popState];
  return self;
}

- ringBell
{
  char bell = '\a';
  write (fd, &bell, 1);
  return self;
}

@end
